import 'package:flutter/foundation.dart';

import 'result.dart';

/// 网络请求状态
enum RequestState {
  /// 默认
  idle,

  /// 请求中
  loading,

  /// 成功
  success,

  /// 失败
  failed,
}

/// 列表数据。
abstract class ListViewModel<T> with ChangeNotifier {
  /// 列表数据。
  ListViewModel({
    this.perPage = 10,
    this.lastPage = -1,
  });

  /// 每页多少个 item
  int perPage;

  /// 总页数。默认为 -1，不设限。
  int lastPage;

  /// 当前页数
  int _currentPage = 0;

  /// 根据接口实际数据来确定总页数。
  /// 如果某页 [_currentPage] 的数据为 0 个，
  /// 则设置 [_innerLastPage] = [_currentPage]。
  int _innerLastPage = -1;

  /// 数据列表
  List<T>? _list;

  /// 网络请求状态
  RequestState state = RequestState.idle;

  /// 当前页数
  int get currentPage => _currentPage;

  /// 数据个数
  int get itemCount => _list?.length ?? 0;

  /// 列表
  List<T>? get list => _list;

  bool get isSuccess => state == RequestState.success;
  bool get isFailed => state == RequestState.failed;
  bool get isEmpty => itemCount == 0;
  bool get isNotEmpty => itemCount > 0;

  /// 是否首次请求并失败了
  bool get isFailedOnFirstRequest => _currentPage <= 0 && state == RequestState.failed;

  /// 是否有下一页。
  bool get hasNextPage {
    if (lastPage < 0 && _innerLastPage < 0) {
      return true;
    }

    if (lastPage >= 0) {
      return _currentPage < lastPage;
    } else {
      return _currentPage < _innerLastPage;
    }
  }

  /// 获取第一页数据
  Future<Result<List<T>>> requestFirstPage() async {
    state = RequestState.loading;
    _innerLastPage = -1;

    final result = await requestData(page: 1);

    do {
      if (result.isFailed) {
        state = RequestState.failed;
        _list ??= <T>[];
        break;
      }

      state = RequestState.success;

      _currentPage = 1;

      if (_list == null) {
        _list = <T>[];
      } else {
        _list!.clear();
      }

      final data = result.data;
      if (data != null && data.isNotEmpty) {
        _list!.addAll(data);
      }
    } while (false);

    return result;
  }

  /// 获取下一页数据
  Future<Result<List<T>>> requestNextPage() async {
    if (_currentPage == 0) {
      return requestFirstPage();
    }

    state = RequestState.loading;

    final result = await requestData(page: _currentPage + 1);

    do {
      if (result.isFailed) {
        state = RequestState.failed;
        _list ??= <T>[];
        break;
      }

      state = RequestState.success;

      final data = result.data;

      if (data == null) break;

      if (data.isEmpty) {
        _innerLastPage = _currentPage;
        break;
      }

      _currentPage += 1;

      if (_list == null) {
        _list = data.toList();
      } else {
        _list!.addAll(data);
      }
    } while (false);

    return result;
  }

  /// 获取数据接口。子类需实现该方法。
  ///
  /// 使用 view model 时，请避免直接使用该方法。
  /// 请按需使用 [requestFirstPage] 或 [requestNextPage]
  Future<Result<List<T>>> requestData({required int page}) async {
    assert(false);
    return Result.failed(code: "200", msg: '未实现');
  }

  /// 删除列表某项
  T? removeAt(int index) {
    if (_list == null || _list!.length <= index) {
      return null;
    }

    return _list!.removeAt(index);
  }

  /// 重置数据
  void reset() {
    _list = null;
    state = RequestState.idle;
    _currentPage = 0;
    _innerLastPage = -1;
  }

  /// 通知列表刷新。
  void reload() => notifyListeners();
}
